/**
 * <pre>
 * @(#)ChartUtilities.java 1.00 2009-8-26
 * 
 * Copyright (c) 1998, 2009 Regular Individual. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * Contributor(s):
 *     Haixu Huang
 * </pre>
 **/
package cn.sh.huang.chart.ext;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;

import cn.sh.huang.chart.ext.enumtype.Extension;
import cn.sh.huang.chart.ext.enumtype.Overflow;

/**
 * <pre>
 * ChartUtilities ...
 * 
 * @version 1.0
 * </pre>
 */
public final class ChartUtilities
{
    private ChartUtilities()
    {
    }

    public static Dimension fitRect(Rectangle rect, Dimension size)
    {
        size.width = Math.min(rect.width, size.width);
        size.height = Math.min(rect.height, size.height);
        return size;
    }

    public static Image getBgClearedImage(Image image, final Color color)
    {
        ImageFilter filter = new RGBImageFilter() {
            // the color we are looking for... Alpha bits are set to opaque
            public int markerRGB = color.getRGB() | 0xFF000000;

            public final int filterRGB(int x, int y, int rgb)
            {
                if ((rgb | 0xFF000000) == markerRGB) {
                    // Mark the alpha bits as zero - transparent
                    return 0x00FFFFFF & rgb;
                } else {
                    // nothing to do
                    return rgb;
                }
            }
        };

        ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
        return Toolkit.getDefaultToolkit().createImage(ip);
    }

    /**
     * <pre>
     *   To get the preferred width and index of an extra-long label
     * </pre>
     * 
     * @param fm
     *            font metrics
     * @param label
     * @param width
     *            Rendering Area width
     * @return
     */
    public static String getPreferredSubLabel(FontMetrics fm, String label, int width)
    {
        return getPreferredSubLabel(fm, label, width, Overflow.TAIL, Extension.TANGENT);
    }

    private static final String TANGENT_SUFFIX = "..", NORMAL_SUFFIX = ":";

    private static final String getSuffix(Extension e)
    {
        return e.equals(Extension.TANGENT) ? TANGENT_SUFFIX : NORMAL_SUFFIX;
    }

    private static int getStringWidth(FontMetrics fm, String s, Extension e)
    {
        return e.equals(Extension.TANGENT) ? fm.stringWidth(s) : fm.getHeight() * s.length();
    }

    private static int getCharWidth(FontMetrics fm, char chr, Extension e)
    {
        return e.equals(Extension.TANGENT) ? fm.charWidth(chr) : fm.getHeight();
    }

    public static String getPreferredSubLabel(FontMetrics fm, String label, int width, Overflow o, Extension e)
    {
        if (getStringWidth(fm, label, e) <= width) {
            return label;
        }

        int len = 0, start = 0, size = label.length(), idx = -1;
        if (o.equals(Overflow.BOTH)) {
            len = getStringWidth(fm, getSuffix(e), e) * 2;
            start = label.length() / 2;
            idx = start;
        } else if (o.equals(Overflow.TAIL)) {
            len = getStringWidth(fm, getSuffix(e), e);
            start = 0;
            idx = start;
        } else {
            len = getStringWidth(fm, getSuffix(e), e);
            start = size;
            idx = start - 1;
        }
        int end = start;
        while (end - start < size) {
            len += getCharWidth(fm, label.charAt(idx), e);
            if (len >= width) {
                break;
            }
            if (o.equals(Overflow.BOTH)) {
                if ((end - start) % 2 == 0) {
                    end++;
                    idx = start - 1;
                } else {
                    start--;
                    idx = end;
                }
            } else if (o.equals(Overflow.TAIL)) {
                end++;
                idx = end;
            } else {
                start--;
                idx = start - 1;
            }
        }
        if (o.equals(Overflow.BOTH)) {
            if (end == start) {
                return getSuffix(e);
            } else {
                return getSuffix(e) + label.substring(start, end) + getSuffix(e);
            }
        } else if (o.equals(Overflow.TAIL)) {
            return label.substring(start, end) + getSuffix(e);
        } else {
            return getSuffix(e) + label.substring(start, end);
        }
    }
}
